#include"Task.hpp"
#include<pthread.h>
#include<iostream>
#include<queue>
#include"Log.hpp"
#define THREAD_NUM 5

class ThreadPool 
{
 private:
   int _thread_num;
   pthread_mutex_t lock;
   pthread_cond_t cond;
   std::queue<Task> task_queue;
 private:

   void Lock()
   {
     pthread_mutex_lock(&lock);
   }
   void UnLock()
   {
     pthread_mutex_unlock(&lock);
   }
   void Wait()
   {
     pthread_cond_wait(&cond,&lock);
   }
   void WakeUp()
   {
     pthread_cond_signal(&cond);
   }
   bool TaskQueueIsEmpty()
   {
     return task_queue.empty();
   }
   void PopTask(Task& task)
   {   
     LOG(INFO,"PopTask");
       task=task_queue.front();
       task_queue.pop();
   }
 static void* ThreadRoutine(void* args)
   {
     auto* tp = (ThreadPool*)args;
      while(true)
      {
        tp->Lock();
        while(tp->TaskQueueIsEmpty())
        {
          tp->Wait();
        }
        
        Task t;
        tp->PopTask(t);

        tp->UnLock();
        t.ToBeginSolve();         

      }
   }
 public:
   ThreadPool(int thread_num=THREAD_NUM):_thread_num(thread_num)
   {
    pthread_mutex_init(&lock,nullptr);
    pthread_cond_init(&cond,nullptr);
   };

   bool InitThreadPool()
   {
     for(int i=0;i<_thread_num;i++)
     {
       pthread_t tid;
      if( pthread_create(&tid,nullptr,ThreadRoutine,this) != 0 )
      {
          LOG(FATAL,"Create ThreadPool Error!");
          return false;
      }

       pthread_detach(tid);
     }
     LOG(INFO,"Create ThtreadPool Success!");
     return false;
   }
   void PushTask(const Task& task)
   {
     Lock();
     LOG(INFO,"PushTask");
     task_queue.push(task);
     UnLock();
     WakeUp();
   }

};
